﻿using System;
using System.ComponentModel;
using System.Linq;
using ProjectEuler.Extensions;
using ProjectEuler.Linq;

namespace ProjectEuler.Problems
{
    [EulerProblem(27, -59231)]
    [Description("Find a quadratic formula that produces the maximum number of primes for consecutive values of n.")]
    internal sealed class Problem027 : EulerProblem
    {
        public override Object Solve()
        {
            return (from a in (-999).To(1000)
                   from b in (-999).To(1000)
                   select new
                   {
                       p = (a * b),
                       n = GetNumberOfConsecutivePrimes(a, b),
                   })
                   .WithMax(x => x.n)
                   .p;
        }

        private Int32 GetNumberOfConsecutivePrimes(Int32 a, Int32 b)
        {
            if (a == 0)
            {
                return IsPrimeMemoized(b) ? 1 : 0;
            }

            var n = 0;

            while (IsPrimeMemoized((n * n) + (a * n) + b))
            {
                n++;
            }

            return n;
        }

        private readonly Func<Int32, Boolean> IsPrimeMemoized = Functional.Memoize<Int32, Boolean>(Numeric.IsPrime);
    }
}
